package com.bree.erp.service.stateless;

import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.bree.erp.entity.GroupType;
import com.bree.erp.entity.Permission;
import com.bree.erp.entity.PermissionId;
import com.bree.erp.entity.PrefixSequence;
import com.bree.erp.entity.Project;
import com.bree.erp.entity.PurchaseRequisition;
import com.bree.erp.entity.Status;
import com.bree.erp.entity.User;
import com.bree.erp.service.PermissionService;
import com.bree.erp.service.PrefixSequenceService;
import com.bree.erp.service.PurchaseRequisitionService;

@Stateless
public class PurchaseRequisitionServiceBean implements
		PurchaseRequisitionService {

	private static Logger LOG = Logger
			.getLogger(PurchaseRequisitionServiceBean.class);

	@PersistenceContext()
	private EntityManager em;
	
	@EJB
	private PermissionService permissionService;
	
	@EJB 
	private PrefixSequenceService sequenceService;

	public PurchaseRequisitionServiceBean() {

	}

	public PurchaseRequisitionServiceBean(EntityManager em) {
		this.em = em;
	}

	@Override
	public Collection<PurchaseRequisition> list(String namedQuery, User user) {

		TypedQuery<PurchaseRequisition> query = em.createNamedQuery(namedQuery,
				PurchaseRequisition.class).setParameter("user", user);

		return query.getResultList();
	}

	@Override
	public Collection<PurchaseRequisition> list() {

		TypedQuery<PurchaseRequisition> query = em.createNamedQuery(
				PurchaseRequisition.QUERY_FIND_ALL_PURCHASEREQUISTION,
				PurchaseRequisition.class);

		return query.getResultList();
	}

	@Override
	public PurchaseRequisition create(User user, Project project,
			String description) {

		PurchaseRequisition pr = new PurchaseRequisition();

		pr.setProject(project);
		pr.setDescription(description);
		pr.setStatus(Status.OPEN);

		pr.setOwner(user);
		pr.auditCreate(user);

		em.persist(pr);

		return pr;
	}

	@Override
	public void delete(PurchaseRequisition purchaseRequisition) {

		em.remove(purchaseRequisition);

	}

	@Override
	public PurchaseRequisition read(Long id, boolean refresh) {

		PurchaseRequisition entity = em.find(PurchaseRequisition.class, id);
		if (refresh && entity != null) {
			em.refresh(entity);
		}

		return entity;
	}

	@Override
	public PurchaseRequisition read(Long id) {

		return read(id, false);
	}

	@Override
	public PurchaseRequisition update(Long id, Project project,
			String description, String jobArea, String remarks, User user) {

		PurchaseRequisition entity = read(id);

		entity.setProject(project);
		entity.setDescription(description);
		entity.setJobarea(jobArea);
		entity.setRemarks(remarks);

		entity.auditUpdate(user);

		return entity;
	}

	@Override
	public PurchaseRequisition update(Long id, Long projectId,
			String description, String jobArea, String remarks, String userId) {
		Project project = em.find(Project.class, projectId);
		User user = em.find(User.class, userId);

		return update(id, project, description, jobArea, remarks, user);
	}

	@Override
	public void delete(Long id) {
		PurchaseRequisition entity = read(id);

		em.remove(entity);
	}

	@Override
	public PurchaseRequisition submit(Long id) {
		PurchaseRequisition entity = read(id);

		entity.setRequisitionDate(new Date());
		entity.setStatus(Status.PENDING);

		return entity;
	}

	@Override
	public PurchaseRequisition reopen(Long id, String userId) {
		PurchaseRequisition entity = read(id);
		User user = em.find(User.class, userId);
		entity.setStatus(Status.OPEN);
		entity.auditUpdate(user);
		return entity;
	}

	@Override
	public PurchaseRequisition approve(Long id, String remarks, String userId) {
		PurchaseRequisition entity = read(id);
		User user = em.find(User.class, userId);
		entity.setRemarks(remarks);
		entity.setStatus(Status.APPROVED);

		// create PR number
		if(entity.getPrNumber() == null) {
			String prefix = createPrefix(entity);
			PrefixSequence prnum = sequenceService.create(prefix);
			entity.setPrNumber(prnum);
		}
		
		entity.auditApprove(user);
		
		return entity;
	}

	private String createPrefix(PurchaseRequisition entity) {
		
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		String year = calendar.get(Calendar.YEAR) + "";
		
		String prefix = entity.getProject().getCode() + "-" + year.substring(2); 
		
		return prefix;
	}

	@Override
	public Collection<PurchaseRequisition> list(Status status) {

		TypedQuery<PurchaseRequisition> query = em.createNamedQuery(
				PurchaseRequisition.QUERY_FIND_PURCHASEREQUISTION_PER_STATUS,
				PurchaseRequisition.class).setParameter("status", status);

		return query.getResultList();
	}

	@Override
	public Collection<PurchaseRequisition> list(String userId, Long projectId, Status status) {

		if (projectId == null || StringUtils.isBlank(userId)) {
			LOG.error("NULL User ID or project ID passed! Returning empty list.");
			return Collections.emptyList();
		}

		Project project = em.find(Project.class, projectId);
		
		PermissionId permId = new PermissionId(userId, projectId);
		Permission permission = permissionService.read(permId );
		
		boolean isManager = permission != null 
				&& (permission.getGroups().contains(GroupType.MANAGER) || permission.getGroups().contains(GroupType.PURCHASER));
		
		LOG.debug("isManager: " + isManager + "; project: " + projectId + "; status: " + status);

		TypedQuery<PurchaseRequisition> query;
		
		if(isManager) {
			query = em
					.createNamedQuery(
							PurchaseRequisition.QUERY_FIND_PURCHASEREQUISTION_PER_PROJSTATUS,
							PurchaseRequisition.class)
					.setParameter("project", project)
					.setParameter("status", status);
		} else {
			
			User user = em.find(User.class, userId);

			query = em
					.createNamedQuery(
							PurchaseRequisition.QUERY_FIND_PURCHASEREQUISTION_PER_USERPROJSTATUS,
							PurchaseRequisition.class)
					.setParameter("user", user)
					.setParameter("project", project)
					.setParameter("status", status);
					
		}

		return query.getResultList();
	}

	@Override
	public void updateStatusFromOrders(Long id) {

		PurchaseRequisition entity = read(id, true);

		if (entity.isHasPendingOrders()) {
			entity.setStatus(Status.INPROGRESS);
		}

	}

	@Override
	public PurchaseRequisition confirm(Long id, String userId) {
		PurchaseRequisition entity = read(id);

		entity.setStatus(Status.CONFIRMED);

		User user = em.find(User.class, userId);
		entity.auditUpdate(user);

		return entity;
	}

	@Override
	public int countItem(String userId, Long projectId, Status status) {

		User user = em.find(User.class, userId);
		Project project = em.find(Project.class, projectId);

		Query query = em
				.createNamedQuery(
						PurchaseRequisition.QUERY_COUNT_OPENPR_PER_USERPROJ)
				.setParameter("user", user).setParameter("project", project)
				.setParameter("status", status);

		Long result = (Long) query.getSingleResult();

		return result.intValue();
	}

	@Override
	public PrefixSequence updateSequence(Long id) {
		
		PurchaseRequisition entity = read(id);
		
		PrefixSequence prNumber = entity.getPrNumber();
		if(prNumber != null) {
			prNumber = sequenceService.update(prNumber.getId());
			
			return prNumber;
		}
			
	
		
		
		return null;
	}

}
